package com.cancer.common.util;

import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.springframework.web.servlet.view.document.AbstractExcelView;


public class MyExcelView<T> extends AbstractExcelView {

	public static class Header<T>{
		
		public Header(){}
		public Header(String displayName,String propertyName){
			this.displayName = displayName;
			this.propertyName = propertyName;
		}
		
		public Header(String displayName,String propertyName,Class enumType){
			this.displayName = displayName;
			this.propertyName = propertyName;
			this.enumType = enumType;
		}
		
		/**
		 * 属性显示名称
		 */
		private String displayName;
		
		/**
		 * 属性名
		 */
		private String propertyName;
		
		/**
		 * 特殊处理类型
		 * 枚举等
		 */
		private Class enumType;
		
		public String getDisplayName() {
			return displayName;
		}

		public void setDisplayName(String displayName) {
			this.displayName = displayName;
		}

		public String getPropertyName() {
			return propertyName;
		}

		public void setPropertyName(String propertyName) {
			this.propertyName = propertyName;
		}
		
		public Class getEnumType() {
			return enumType;
		}
		
		public void setEnumType(Class enumType) {
			this.enumType = enumType;
		}
		
	}
	
	private static String doubleRegex = null;

	private static String chineseRegex = null;
	
	static{
		doubleRegex = "^\\d+\\.\\d+$";
		chineseRegex = "^[\u4e00-\u9fa5]+$";
	}
	
	/**
	 * 数据
	 */
	private List<T> dataList;
	
	/**
	 * 表头数据
	 */
	private List<Header> headerList;
	
	/**
	 * 生成序号
	 */
	private Boolean isMakeOrderNo = false;
	
	/**
	 * excel文件名
	 */
	private String fileName;
	
	public MyExcelView() {}
	
	public MyExcelView(List<T> datalist,List<Header> headerList) {
		this.dataList = datalist;
		this.headerList = headerList;
	}
	
	public MyExcelView(List<T> datalist,List<Header> headerList,Boolean isMakeOrderNo) {
		this.dataList = datalist;
		this.headerList = headerList;
		this.isMakeOrderNo = isMakeOrderNo;
	}
	
	public MyExcelView(List<T> datalist,List<Header> headerList,Boolean isMakeOrderNo,String fileName) {
		this.dataList = datalist;
		this.headerList = headerList;
		this.isMakeOrderNo = isMakeOrderNo;
		this.fileName = fileName;
	}
	
    @Override  
    protected void buildExcelDocument(Map<String, Object> obj,  
            HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response)  
            throws Exception {  
		if (dataList != null && headerList != null) {
			HSSFSheet sheet = workbook.createSheet("数据信息");
			HSSFRow row = sheet.createRow((int) 0);
			HSSFCellStyle style = workbook.createCellStyle();
			style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
			HSSFCell cell = row.createCell((short) 0);
			int cellNum=0;
			int propertySize = headerList.size();
			int headNo = 0;
			for (int i = 0; i < propertySize; i++) {
				if(i==0 && isMakeOrderNo){
					cell.setCellValue("序号");
					sheet.setColumnWidth(i, 1500);
					cell.setCellStyle(style);
					cell = row.createCell(++cellNum);
					headNo = 1;
				}
				Header header = headerList.get(i);
				String title = header.getDisplayName();
				cell.setCellValue(title);
				sheet.setColumnWidth(headNo, title.length()*2*256);
				cell.setCellStyle(style);
				cell = row.createCell(++cellNum);
				headNo++;
			}
			int rowNum=0;
			T dataMap=null;
			int dataSize = dataList.size();
			
			HSSFCellStyle contentStyle = workbook.createCellStyle();
			contentStyle.setAlignment(XSSFCellStyle.ALIGN_LEFT);
			contentStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));
			for (int i = 0; i < dataSize; i++) {
				dataMap=dataList.get(i);
				row = sheet.createRow(++rowNum);
				int cellNo = 0;
				for (int j = 0;j<propertySize;j++) {
					if(j == 0 && isMakeOrderNo){
						cell = row.createCell(0);
						cell.setCellValue(i+1);
						cellNo=1;
					}
					Header header = headerList.get(j);
					cell = row.createCell(cellNo);
					if(!StringUtils.isNotBlank(header.getPropertyName())){
						cell.setCellValue("");
						continue;
					}
					Object cellValue = ReflectUtil.getProperty(dataMap, header.getPropertyName());
					if(cellValue != null && cellValue.toString() != ""){
						String cellValueStr = null;
						Class clzz = header.getEnumType();
						if(clzz != null){
							if(clzz == Boolean.class){
								cellValueStr = cellValue.toString().equals("0")?"否":"是";
							}else if(clzz == Date.class){
								//cellValueStr = DateUtil.getDateFormatString(String.valueOf(cellValue), "yyyy-MM-dd HH:mm:ss");
							}else{
								//枚举类型，需转换
								//cellValueStr = EnumUtil.getDescByValue(header.getEnumType(), cellValue);
							}
						}else{
							cellValueStr = String.valueOf(cellValue);
						}
						if(StringUtils.isNotBlank(cellValueStr)){
							int width = sheet.getColumnWidth(cellNo);
							int width2 = cellValueStr.length()*2*160;
							if(StringUtil.matches(cellValueStr, chineseRegex)){
								width2 = width2*2;
							}
							if(width2 > 10000){
								width2 = 10000;
							}
							if(width2>width){
								sheet.setColumnWidth(cellNo, width2);
							}
						}
						if(StringUtil.matches(cellValueStr,doubleRegex)){
							cell.setCellStyle(contentStyle);
							cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
							cell.setCellValue(Utils.toDouble(cellValue));
						}else{
							cell.setCellValue(cellValueStr);
						}
					}else{
						cell.setCellValue("");
					}
					cellNo++;
				}
			}
	    }
		if(!StringUtils.isNotBlank(fileName)){
			//fileName = CodeUtils.getCode("Geek+")+RandomUtil.randomInt(10);
		}
		fileName = fileName+".xls";
        response.setContentType("application/vnd.ms-excel");     
        response.setHeader("Content-disposition", "attachment;filename=" + new String(fileName.getBytes("gbk"),"ISO-8859-1"));     
        OutputStream ouputStream = response.getOutputStream();     
        workbook.write(ouputStream);     
        ouputStream.flush();     
        ouputStream.close();   
    } 
}
